package com.tiancheng.trade.authserver.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tiancheng.trade.authserver.entity.AuthUser;
import com.tiancheng.trade.authserver.entity.UserThirdInfo;
import com.tiancheng.trade.authserver.enums.SignUpTypeEnum;
import com.tiancheng.trade.authserver.enums.ThirdPlatformEnums;
import com.tiancheng.trade.authserver.enums.UserGenderEnum;
import com.tiancheng.trade.authserver.mapper.AuthUserMapper;
import com.tiancheng.trade.authserver.service.IAuthUserMapRoleService;
import com.tiancheng.trade.authserver.service.IAuthUserService;
import com.tiancheng.trade.authserver.service.IUserThirdInfoService;
import com.tiancheng.trade.authserver.utils.IdGenerateUtils;
import com.tiancheng.trade.authserver.utils.PasswordService;
import com.tiancheng.trade.authserver.vo.UserAddUpdateVO;
import com.tiancheng.trade.authserver.vo.UserSignUpRequestVO;
import com.tiancheng.trade.commom.core.exception.error.AuthErrorInfoEnum;
import com.tiancheng.trade.commom.web.http.PlatformRequest;
import com.tiancheng.trade.commom.core.utils.IdWorkerUtils;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.Optional;

/**
 * @Author: likailun
 * @Description: 用户 servie实现
 * @Date: create in 2024/10/21 17:21
 */
@Service
public class AuthUserServiceImpl extends ServiceImpl<AuthUserMapper, AuthUser> implements IAuthUserService {

    @Resource
    private IUserThirdInfoService userThirdInfoService;
    @Resource
    private PlatformRequest platformRequest;
    @Resource
    private IAuthUserMapRoleService authUserMapRoleService;

    @Override
    public AuthUser getByPhone(String phone) {
        return this.getOne(new LambdaQueryWrapper<AuthUser>().eq(AuthUser::getPhone, phone));
    }

    @Override
    public AuthUser getByEmail(String email) {
        return this.getOne(new LambdaQueryWrapper<AuthUser>().eq(AuthUser::getEmail, email));
    }

    @Override
    public AuthUser getByUserName(String userName) {
        return this.getOne(new LambdaQueryWrapper<AuthUser>().eq(AuthUser::getName, userName));
    }

    @Transactional
    @Override
    public Long signUp(UserSignUpRequestVO param) {
        final Optional<SignUpTypeEnum> typeEnum = SignUpTypeEnum.getByCode(param.getSignUpType());
        AuthErrorInfoEnum.AUTH_ACCOUNT_REGISTER_UN_SUPPORT.assertIsTrue(typeEnum.isPresent());
        final SignUpTypeEnum signUpTypeEnum = typeEnum.get();
        if (signUpTypeEnum == SignUpTypeEnum.web_user) {
            AuthErrorInfoEnum.AUTH_ACCOUNT_REGISTER_USERNAME_NOT_NULL.assertIsTrue(StringUtils.isNotEmpty(param.getName())
                    && StringUtils.isNotEmpty(param.getPassword()));
        }
        if (signUpTypeEnum == SignUpTypeEnum.app_code) {
            AuthErrorInfoEnum.AUTH_ACCOUNT_REGISTER_PHONE_CODE_NOT_NULL.assertIsTrue(StringUtils.isNotEmpty(param.getPhone())
                    && StringUtils.isNotEmpty(param.getPassword()) && StringUtils.isNotEmpty(param.getCode()));
            // TODO 校验短信验证码
        }
        PasswordService.validateRule(param.getPassword());
        AuthUser user = createNewUser(param);
        return user.getId();
    }

    @NotNull
    private AuthUser createNewUser(UserSignUpRequestVO param) {
        AuthUser user = this.beforeCreateGetUser(param.getEmail(), param.getPhone());
        boolean newSignUp = false;
        if (null == user) {
            newSignUp = true;
            user = new AuthUser();
            user.setId(IdWorkerUtils.getInstance().nextId());
            if (StringUtils.isNotEmpty(param.getEmail())) {
                user.setName("user" + param.getEmail());
            } else {
                user.setName("user" + param.getPhone());
            }
            user.setName(param.getName());
            user.setPhone(StringUtils.isNotEmpty(param.getPhone()) ? param.getPhone() : null);
            user.setEmail(StringUtils.isNotEmpty(param.getEmail()) ? param.getEmail() : null);
            user.setStatus(0);
            user.setIsTourist(false);
            user.setSignUpDate(new Date());
            user.setPasswordValidDays(30);
            user.setPasswordModifiedDate(System.currentTimeMillis() / 1000);
            user.setCreatedDt(LocalDateTime.now());
            if (param.getPassword() != null && !param.getPassword().isEmpty()) {
                PasswordService.validateRule(param.getPassword());
                user.setPassword(PasswordService.passwordEncryption(param.getPassword(), user.getId().toString()));
            }
        }
        final UserAddUpdateVO userAddUpdateVO = new UserAddUpdateVO();
        userAddUpdateVO.setEmail(param.getEmail());
        userAddUpdateVO.setName(param.getName());
        userAddUpdateVO.setPassword(param.getPassword());
        userAddUpdateVO.setPhone(param.getPhone());

        UserThirdInfo userThirdInfo = this.getUserThirdInfo(user, userAddUpdateVO);
        this.updateUserThirdInfo(user, userThirdInfo);
        if (newSignUp) {
            this.save(user);
            this.afterSaveUser(user, userAddUpdateVO);
        }
        return user;
    }

    protected void afterSaveUser(AuthUser user, UserAddUpdateVO param) {
        this.authUserMapRoleService.saveUserRole(user.getId(), param.getRoleIds());
    }


    protected void updateUserThirdInfo(AuthUser user, UserThirdInfo userThirdInfo) {
        if (!ThirdPlatformEnums.tiancheng.name().equals(userThirdInfo.getPlatform())) {
            userThirdInfo.setUserId(user.getId());
            userThirdInfo.setPhone(user.getPhone());
            this.userThirdInfoService.updateById(userThirdInfo);
            this.initTengyunThirdInfo(user, userThirdInfo);
        }
    }

    public UserThirdInfo getUserThirdInfo(AuthUser user, UserAddUpdateVO param) {
        UserThirdInfo userThirdInfo = this.userThirdInfoService.getByClientIdAndUserId(ThirdPlatformEnums.tiancheng,
                platformRequest.getServiceConfig().getClientId(), user.getId());
        if (userThirdInfo == null) {
            userThirdInfo = new UserThirdInfo();
            userThirdInfo.setPlatform(ThirdPlatformEnums.tiancheng.name());
            userThirdInfo.setClientId(platformRequest.getServiceConfig().getClientId());
            userThirdInfo.setUserId(user.getId());
            userThirdInfo.setOpenId(IdGenerateUtils.generateOpenId(user.getId(),
                    platformRequest.getServiceConfig().getClientId()));
            userThirdInfo.setNick(param.getName());
            userThirdInfo.setAvatar(param.getAvatar());
            userThirdInfo.setGender(UserGenderEnum.unknown.getCode());
            userThirdInfo.setPhone(param.getPhone());
            userThirdInfo.setCreatedDt(LocalDateTime.now());
            this.userThirdInfoService.save(userThirdInfo);
        }
        return userThirdInfo;
    }

    protected void initTengyunThirdInfo(AuthUser user, UserThirdInfo thirdInfo) {
        UserThirdInfo tengyunThirdInfo = this.userThirdInfoService.getByClientIdAndUserId(ThirdPlatformEnums.tiancheng,
                platformRequest.getServiceConfig().getClientId(), user.getId());
        if (tengyunThirdInfo == null) {
            tengyunThirdInfo = new UserThirdInfo();
        }
        tengyunThirdInfo.setUserId(thirdInfo.getUserId());
        tengyunThirdInfo.setOpenId(IdGenerateUtils.generateOpenId(thirdInfo.getUserId(),
                platformRequest.getServiceConfig().getClientId()));
        tengyunThirdInfo.setPlatform(ThirdPlatformEnums.tiancheng.name());
        tengyunThirdInfo.setClientId(platformRequest.getServiceConfig().getClientId());
        if (tengyunThirdInfo.getGender() == null || tengyunThirdInfo.getGender().equals(UserGenderEnum.unknown.getCode())) {
            if (thirdInfo.getGender() != null && thirdInfo.getGender().equals(UserGenderEnum.unknown.getCode())) {
                tengyunThirdInfo.setGender(thirdInfo.getGender());
            }
        }
        if (StringUtils.isEmpty(tengyunThirdInfo.getLanguage()) && StringUtils.isNotEmpty(thirdInfo.getLanguage())) {
            tengyunThirdInfo.setLanguage(thirdInfo.getLanguage());
        }
        if (StringUtils.isEmpty(tengyunThirdInfo.getCountry()) && StringUtils.isNotEmpty(thirdInfo.getCountry())) {
            tengyunThirdInfo.setCountry(thirdInfo.getCountry());
        }
        if (StringUtils.isEmpty(tengyunThirdInfo.getProvince()) && StringUtils.isNotEmpty(thirdInfo.getProvince())) {
            tengyunThirdInfo.setProvince(thirdInfo.getProvince());
        }
        if (StringUtils.isEmpty(tengyunThirdInfo.getCity()) && StringUtils.isNotEmpty(thirdInfo.getCity())) {
            tengyunThirdInfo.setCity(thirdInfo.getCity());
        }
        if (StringUtils.isEmpty(tengyunThirdInfo.getAvatar()) && StringUtils.isNotEmpty(thirdInfo.getAvatar())) {
            tengyunThirdInfo.setAvatar(thirdInfo.getAvatar());
        }
        if ((StringUtils.isEmpty(tengyunThirdInfo.getNick()) || tengyunThirdInfo.getNick().equals("user" +
                user.getPhone())) && StringUtils.isNotEmpty(thirdInfo.getNick())) {
            tengyunThirdInfo.setNick(thirdInfo.getNick());
        }
        tengyunThirdInfo.setPhone(thirdInfo.getPhone());
        if (tengyunThirdInfo.getId() == null) {
            this.userThirdInfoService.save(tengyunThirdInfo);
        } else {
            this.userThirdInfoService.updateById(tengyunThirdInfo);
        }
    }

    /**
     * 创建用户前获取存在用户
     *
     * @param phone 注册电话
     */
    protected AuthUser beforeCreateGetUser(String email, String phone) {
        AuthUser user;
        if (StringUtils.isNotEmpty(phone)) {
            user = this.getByPhone(phone);
        } else {
            user = this.getByEmail(email);
        }
        return user;
    }
}
